Introdução à Lógica de Programação

Aula 14 - Objetos



Helder Jefferson Ferreira da Luz

helder.luz@ifpr.edu.br

Objetivos

  • Entender o que são objetos e como eles nos ajudam a agrupar informações.
  • Aprender a criar e manipular objetos literais.
  • Trabalhar com estruturas de dados compostas.

Onde as listas falham?

Até agora, usamos listas para agrupar dados similares.

const nomes = ['João', 'Maria', 'José', 'João', 'Pedro', 'Ana'];

nomes.sort();
console.log(nomes);

Entretanto, há casos em que é necessário armazenar informações relacionadas, como os dados de uma pessoa, onde a lista não é o ideal.

Onde as listas falham?

let usuario = ["Ana", "Silva", 30, "ana.silva@email.com"];

console.log(usuario[2]); // O que o índice 2 significa? Idade? Altura?

As listas são ótimas para dados ordenados, mas perdem o contexto. E se a ordem mudar?

const nomes = ['João', 'Maria', 'Pedro']
const idades = [25, 30, 28]
const sexos = ['M', 'F', 'M']
for (let i = 0; i < nomes.length; i++) {
  console.log(`Nome: ${nomes[i]}, Idade: ${idades[i]}, Sexo: ${sexos[i]}`)
}

Onde as listas falham?

Desvantagens:

  • Risco de dessincronização: Se você remover idades[1], precisa lembrar de remover nomes[1] e sexos[1]. Um erro aqui corrompe todos os dados.
  • Falta de coesão: Os dados de uma única pessoa estão espalhados por três listas.
  • Difícil de gerenciar: Para passar os dados de "Maria" para uma função, você precisaria passar nomes[1], idades[1] e sexos[1] separadamente.

Objetos resolvem isso, permitindo agrupar dados relacionados com chaves.

O que são objetos?

Pense em um objeto como um "container" de dados que descreve uma única entidade. Em vez de índices numéricos, usamos chaves (nomes) para identificar cada valor.

Um objeto é uma coleção de pares chave-valor.

const pessoa = {
  nome: "Ana", // 'nome' é a chave, "Ana" é o valor
  sobrenome: "Silva",
  idade: 30,
  email: "ana.silva@email.com",
  ativa: true,
};

Isso é chamado de objeto literal.

Propriedades

As "chaves" de um objeto são chamadas de propriedades.

O valor de uma propriedade pode ser de qualquer tipo de dado que já vimos:

  • string
  • number
  • boolean
  • array
  • e até mesmo uma function!

Quando o valor é uma função, damos um nome especial a ele.

Métodos

Quando uma propriedade de um objeto armazena uma função, nós a chamamos de método.

Métodos são ações que o objeto pode realizar.

const carro = {
  marca: "Fiat",
  modelo: "Uno",
  ano: 2001,
  // Um método do objeto 'carro'
  ligar: function () {
    console.log("O " + this.modelo + " está ligando... vrum vrum!");
  },
};

carro.ligar(); // Executando o método

this é uma palavra-chave especial que se refere ao próprio objeto (carro, neste caso).

Acessando propriedades

Existem duas formas de acessar os valores de um objeto:

  1. Notação de Ponto (.): Mais comum e direta.
  2. Notação de Colchetes ([]): Essencial para chaves dinâmicas.
const pessoa = { nome: "Bia", idade: 25 };

// 1. Notação de Ponto
console.log(pessoa.nome); // Bia

// 2. Notação de Colchetes (a chave é uma string)
console.log(pessoa["idade"]); // 25

Ponto vs. colchetes

A notação de colchetes é poderosa quando a chave é uma variável ou contém caracteres especiais.

const pessoa = {
  nome: "Carlos",
  "e-mail": "carlos@exemplo.com", // Chave com hífen
};

let campo = "nome";

// Acessando com uma variável
console.log(pessoa[campo]); // Carlos

// Com notação de ponto, isso falharia:
// console.log(pessoa.campo); // undefined, pois busca a propriedade "campo"

// Acessando chaves com caracteres especiais
console.log(pessoa["e-mail"]); // carlos@exemplo.com
// console.log(pessoa.e-mail); // Erro de sintaxe!

Objetos são referências

Cuidado! Diferente de tipos primitivos (string, number), objetos são manipulados por referência.

Quando você atribui um objeto a outra variável, você não cria uma cópia. Ambas as variáveis apontam para o mesmo objeto na memória.

const produtoA = { nome: "Caneta", preco: 2.0 };

const produtoB = produtoA; // produtoB agora é uma REFERÊNCIA para produtoA

produtoB.preco = 3.0; // Alteramos em B...

console.log(produtoA.preco); // ...e o valor em A também mudou! -> 3.0

const em um objeto não torna suas propriedades imutáveis! Apenas impede que a variável produtoA aponte para outro objeto.

Estruturas compostas: array de objetos

Usamos um array para guardar uma lista, onde cada item da lista é um objeto com dados estruturados.

  • É a forma ideal para representar coleções: lista de usuários, produtos, posts, etc.

const turma = [
  { nome: "Ana", nota: 9, cidade: "Recife" },
  { nome: "Beto", nota: 7, cidade: "Olinda" },
  { nome: "Carla", nota: 10, cidade: "Recife" },
];

// Acessando dados específicos
console.log(`O aluno ${turma[1].nome} tirou nota ${turma[1].nota}.`);

Array de objetos: exemplo

const usuarios = [
    {
        nome: 'João da Silva', 
        idade: 25, 
        sexo: 'M'
    },
    {
        nome: 'Maria da Silva', 
        idade: 30, 
        sexo: 'F'
    },
    {
        nome: 'Pedro da Silva', 
        idade: 28, 
        sexo: 'M'
    }
]

Estruturas compostas: array com arrays

Para acessar os dados de uma lista de listas, é necessário utilizar [linha][coluna]. Consequentemente, sendo necessário dois for para automatizar o processo.

Exemplo
const matriz = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]

for (let i = 0; i < matriz.length; i++) {
  for (let j = 0; j < matriz[i].length; j++) {
    console.log(`Elemento [${i}][${j}]: ${matriz[i][j]}`)
  }
}
1 2 3
4 5 6
7 8 9

Estruturas compostas: objeto com array

Também é comum ter um objeto que, entre suas propriedades, contém um array.

Isso é útil para agrupar informações sobre uma única entidade que possui uma coleção de itens.

const postDoBlog = {
  titulo: "5 Dicas de JavaScript para Iniciantes",
  autor: "Maria Clara",
  visualizacoes: 1500,
  tags: ["#javascript", "#frontend", "#dicas", "#programacao"],
};

// Acessando uma tag específica
console.log(`A primeira tag do post é ${postDoBlog.tags[0]}.`);
console.log(`A segunda tag do post é ${postDoBlog['tags'][1]}.`);


Exemplo de estrutura mais complexa

Iterando com for...of

O for...of permite iterar por cada objeto do array, um por vez.

const alunos = [
  { nome: "Leo", idade: 18 },
  { nome: "Maria", idade: 19 },
  { nome: "José", idade: 20 },
];

for (const aluno of alunos) {
  // A cada iteração, 'aluno' é um objeto diferente
  console.log(`O aluno ${aluno.nome} tem ${aluno.idade} anos.`);
}

Iterando com for...in

Para percorrer as propriedades de um objeto, usamos o for...in. Ele itera sobre as chaves do objeto.

const carro = {
  marca: "Ford",
  modelo: "Ka",
  ano: 2020,
};

for (const chave in carro) {
  // 'chave' é uma string: "marca", "modelo", "ano"
  console.log(`${chave}: ${carro[chave]}`);
}

Atenção: Note que usamos carro[chave] (notação de colchetes) porque o valor da chave é dinâmico a cada iteração. carro.chave não funcionaria!

Desestruturação (Destructuring)

É um "açúcar sintático" (syntax sugar) para extrair valores de objetos ou arrays de forma mais limpa e direta.

O jeito tradicional:

const usuario = {
  nome: "Pedro",
  idade: 42,
  cidade: "Curitiba",
};

const nomeUsuario = usuario.nome;
const idadeUsuario = usuario.idade;

console.log(`${nomeUsuario} tem ${idadeUsuario} anos.`);

Desestruturação na prática

Com desestruturação, o código fica mais enxuto. Criamos variáveis com o mesmo nome das propriedades que queremos extrair.

const usuario = {
  nome: "Pedro",
  idade: 42,
  cidade: "Curitiba",
};

const { nome, idade } = usuario; // desestruturação

console.log(`${nome} tem ${idade} anos.`);

Isso cria duas variáveis, nome e idade, contendo os valores correspondentes do objeto usuario.

Dúvidas? 🤔

Exercícios

  1. Crie uma matriz 3x3 representada por uma lista de listas e:

    • Imprima todos os elementos da matriz.
    • Calcule a soma dos elementos da diagonal principal.
  2. Meu Livro Favorito:

    • Crie um objeto chamado livro que represente seu livro favorito.
    • Ele deve ter as propriedades titulo (string), autor (string), ano (number), paginas (number) e genero (string).
    • Imprima no console o título e o autor do livro.

Exercícios

  1. Expandindo o Livro:

    • Adicione uma nova propriedade ao objeto livro chamada editora (string).
    • Altere o número de páginas para um novo valor.
    • Imprima o objeto livro completo no console.
  2. Descrevendo o Livro:

    • Adicione um método chamado descrever ao objeto livro.
    • Este método deve imprimir no console uma string formatada como: "O livro [TÍTULO] de [AUTOR] tem [PAGINAS] páginas."
    • Chame o método livro.descrever().

Exercícios

  1. Lista de Compras:

    • Crie um array chamado listaDeCompras.
    • Este array deve conter pelo menos 3 objetos, onde cada objeto representa um item da compra e tem as propriedades produto (string), preco (number) e quantidade (number).
  2. Total da Compra:

    • Usando um laço (for...of), itere sobre a listaDeCompras.
    • Calcule o custo total da compra (preço * quantidade de cada item) e armazene em uma variável total.
    • Imprima o valor total no console.

Exercícios

  1. Encontre o Produto:

    • Crie uma função encontrarProduto(lista, nomeDoProduto).
    • A função deve percorrer a lista e retornar o objeto do produto se encontrá-lo.
    • Se não encontrar, deve retornar null.
    • Teste a função buscando por um produto que existe e um que não existe.
  2. Carrinho Elegante:

    • Itere novamente sobre a listaDeCompras usando for...of.
    • Dentro do laço, use a desestruturação para extrair produto, preco e quantidade em variáveis separadas.
    • Imprima uma mensagem para cada item, como: "Produto: [PRODUTO], Preço: R$ [PRECO], Qtd: [QUANTIDADE]".

Exercícios

  1. Dada a seguinte lista de dicionários:

    carros = [
        { marca: "Toyota", modelo: "Corolla", ano: 2020 },
        { marca: "Honda", modelo: "Civic", ano: 2018 },
        { marca: "Ford", modelo: "Focus", ano: 2019 }
    ]
    

    Realize as seguintes tarefas:

    • Adicione um novo carro à lista.
    • Exiba os carros fabricados após 2018.

Exercícios

  1. Crie um programa que represente uma lista com informações de alunos de uma escola. Cada aluno deve ter um nome, uma idade e uma lista com as disciplinas, onde cada posição é um objeto com o nome e a nota nesta disciplina.

    • Após a criação, adicione um novo aluno à lista, informando nome, idade e as disciplinas.
    • Ao final, exiba a lista de alunos com seus respectivos idades, disciplinas e média das notas.
    Exemplo da estrutura que será construída
    const alunos = [
        {
            nome: 'João', idade: 20,
            disciplinas: [
                { nome: 'Matemática', nota: 10 }, { nome: 'Português', nota: 7 }
            ]
        }
    ]
    

Exercícios

  1. Crie uma lista para armazenar informações sobre departamentos de uma empresa. Cada posição da lista deverá ser um objeto referente a um departamento, que armazena o nome do departamento e uma lista de funcionários. Cada funcionário é um objeto com nome do funcionário e salário do mesmo.
    - Adicione pelo menos 2 departamentos e 3 funcionários em cada um.
    - Calcule a soma dos salários de todos os funcionários.
    - Liste o nome do departamento com a média salarial mais alta.

    const departamentos = [
        {
            nome: 'marketing',
            funcionarios: [
                { nome: 'João', salario: 2100 },
                { nome: 'Maria', salario: 3100},
                { nome: 'José', salario: 3200}
            ]
        }
    ]